

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
import java.util.LinkedList;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
 * Servlet implementation class BankingServlet
 */
@WebServlet("/BankingServlet")
public class BankingServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	private static Account userAccnt;

    /**
     * Default constructor. 
     */
    public BankingServlet() {
        userAccnt = new Account();
    }

	/**
	 * This method will be used for AJAX elements
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
				
		String userName = (String) request.getSession().getAttribute("user");
		userAccnt = new Account(userName);
		
		LinkedList<String> names = userAccnt.getAccountNames();
		
		//PrintWriter pw=response.getWriter();
		for(int i=0; i<names.size(); i++){
			request.setAttribute("Account Name:"+i, names.get(i));
			//pw.print(names.get(i));
			//pw.println("<br>");
		}
		//pw.close();
		
		if(request.getParameter("Trans")!=null){
		}else if(request.getParameter("Del")!=null){
			RequestDispatcher d = request.getRequestDispatcher("/DeleteAccnt.jsp");
			if (d != null) {
				d.forward(request,response);
			}
		}else if(request.getParameter("Fzn")!=null){
			
		}

	}

	/**
	 * This method will be used for account functionalities
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		String userName = (String) request.getSession().getAttribute("user");
		userAccnt = new Account(userName);
		
		String reqType = request.getParameter("Trans");
		if(reqType!=null){
			userAccnt.transfer(request.getParameter("from"), request.getParameter("to"), Double.parseDouble(request.getParameter("amt")));
		}else if(request.getParameter("Add")!=null){
			userAccnt.createAccount(request.getParameter("newAccnt"));
			RequestDispatcher d = request.getRequestDispatcher("/AddAccount.jsp");
			if (d != null) {
				d.forward(request,response);
			}
		}else if(request.getParameter("Del")!=null){
			//transfer first
			//get amount to transfer from the "from" account
			double amt = 0;
			String accountNameFrom = request.getParameter("from");
			String accountNameTo = request.getParameter("to");
			PrintWriter pw = response.getWriter();
			response.setContentType("text/html");
			if(userAccnt.accountExists(accountNameFrom))
			{
				amt = userAccnt.getAccountBalance(accountNameFrom);
				String successful = "";
				successful = userAccnt.transfer(accountNameFrom, accountNameTo, amt);
				pw.write("<html>" + successful + "<br>");
				if(successful.contains("successful"))
				{
					successful = userAccnt.deleteAccount(request.getParameter("delete"));
					pw.write(successful + "<br>");
				}
				pw.write("<form action='DeleteAccnt.jsp'><input type='submit' value='Back'></form>" +
						 "<form action=MainPage><input type='submit' value='To Main Page'></form></html>");
				pw.close();
			}
			else
			{
				pw.write("<html>Account " + accountNameFrom + " does not exist.<br>");
				pw.write("<form action='DeleteAccnt.jsp'><input type='submit' value='Back'></form>" +
				 "<form action=MainPage><input type='submit' value='To Main Page'></form></html>");
				pw.close();
			}
//			RequestDispatcher d = request.getRequestDispatcher("/DeleteAcct.jsp");
//			if(d != null)
//				d.forward(request, response);
		}else if(request.getParameter("Fzn")!=null){
			String success = userAccnt.setFrozen(request.getParameter("toFreeze"));
			PrintWriter pw = response.getWriter();
			pw.write(success); 
			RequestDispatcher d = request.getRequestDispatcher("/FreezeAccount.jsp");
			if (d != null) {
				d.forward(request,response);
			}
			pw.close();
		}else if(request.getParameter("View")!=null){
			LinkedList<String> success = userAccnt.getAllAccounts();
			int len = success.size();
			for(int i=0; i < len; i++){
				String attr = "accnt"+i;
				request.setAttribute(attr, success.get(i));
			}
			
			
			RequestDispatcher d = request.getRequestDispatcher("/ViewAccounts.jsp");
			if (d != null) {
				d.forward(request,response);
			}
		}
	}
	
	/**
	 * Reads and writes from a file for the accounts of this user.
	 * File format has 3 attributes for each account:  
	 * 		AccountName|Frozen|Amount
	 * @author Abby S
	 *
	 */
	private static class Account{
		BufferedReader in;
		BufferedWriter out;
		File accntFile;
		LinkedList<String> accountInfo = new LinkedList<String>();
		String account = "";

		
		public Account(String user){
			boolean isNew = false;
			account = "C:/Documents and Settings/Abby S/Desktop/Project3_319/Proj3/WebContent/UserAccounts/" + user +".txt";
			try {
				accntFile = new File(account);//Will be used in the save method
				if(!accntFile.exists()){
					accntFile.createNewFile();
					isNew = true;
				}
				
				
				in =  new BufferedReader(new FileReader(account));
				out = new BufferedWriter(new FileWriter(account, true));
				
				if(isNew){
					out.write("Main|false|1000.00");
				}
				
				//Populate list with accounts for this user
				String line = in.readLine();
				while(line!=null){
					accountInfo.addLast(line);
					line = in.readLine();
				}
				
			} catch (IOException e) {
				// Account does not exist
				e.printStackTrace();
			}
		}
		
		public Account() {
			//Just default, allows for creation of an empty Account object
		}

		//Returns a list for all accounts of the current user
		public LinkedList<String> getAllAccounts(){
			return accountInfo;
		}
		
		public LinkedList<String> getAccountNames(){
			LinkedList<String> retval = new LinkedList<String>();
			for(int i=0; i<accountInfo.size(); i++){
				String temp = accountInfo.get(i);
				retval.add(i, temp.split("\\|")[0]);
			}
			return retval;
		}
		
		public boolean accountExists(String acctName)
		{
			for(String x : accountInfo)
			{
				if(x.split("\\|")[0].equals(acctName))
					return (true);
			}
			return (false);
		}
		
		public double getAccountBalance(String acctName)
		{
			String accountInfo = getAccountInfo(acctName);
			if(accountInfo.equals(""))
				return (0.0);
			return (Double.parseDouble(accountInfo.split("\\|")[2]));
		}
		
		private String getAccountInfo(String acctName)
		{
			int len = accountInfo.size();
			for(int i = 0 ; i < len;  i++)
			{
				String curAcct = accountInfo.get(i);
				if(curAcct.split("\\|")[0].equals(acctName))
					return (curAcct);
			}
			return ("");
		}
		
		/**
		 * Adds an account to this users profile of accounts
		 * @param accountName
		 */
		public void createAccount(String accountName){

			try {
				//out = new BufferedWriter(new FileWriter(account, true));
				String toAdd = accountName + "|false|0.00";
				accountInfo.addLast(toAdd);
				out.newLine();
				out.write(toAdd);
				out.flush();
				//save();
			} catch (IOException e) {
				// ???
				e.printStackTrace();
			}
		}
		
		/**
		 * Transfers money from one account to another.  Same accounts should not
		 * be entered, as that will be handled in the appropriate jsp file
		 * @param fromAccnt
		 * @param toAccnt
		 * @param amt
		 * @return A message stating if there was an error or if the transfer was successful
		 */
		public String transfer(String fromAccnt, String toAccnt, double amt){
			String transferFrom="";
			String transferTo="";
			String temp = "";
			int loc1 = 0;
			int loc2 = 0;
			
			for(int i=0; i<accountInfo.size(); i++){
				temp = accountInfo.get(i);
				if(temp.substring(0, temp.indexOf('|')).equals(fromAccnt)){ transferFrom = temp; loc1=i;}
				if(temp.substring(0, temp.indexOf('|')).equals(toAccnt)){transferTo = temp; loc2=i;}
			}
			if(transferFrom.equals(""))
				return ("Account to transfer from not specified.");
			if(transferTo.equals(""))
				return ("Account to transfer to not specified.");
			if(!accountExists(transferFrom.substring(0, transferFrom.indexOf('|'))))
				return ("Account to transfer from does not exist.");
			if(!accountExists(transferTo.substring(0, transferTo.indexOf('|'))))
				return ("Account to transfer to does not exist.");
			double first = Double.parseDouble(transferFrom.substring(transferFrom.lastIndexOf("|")+1));
			double second = Double.parseDouble(transferTo.substring(transferTo.lastIndexOf("|")+1));
			temp = transferFrom.substring(transferFrom.indexOf("|")+1, transferFrom.lastIndexOf("|"));
			
			if(first<amt) return "Not enough money to transfer!";
			accountInfo.set(loc1, fromAccnt + "|false|" + (first-amt));
			accountInfo.set(loc2, toAccnt + "|false|" + (second+amt));
			save();
			
			return "Transfer successful";
			
		}
		
		//Re-writes the file with the new information, may not be necessary??
		private void save() {
			//accntFile.delete();
			
			try {
				out = new BufferedWriter(new FileWriter(account, false));
				//accntFile.createNewFile();
				for(int i=0; i<accountInfo.size(); i++){
					
					out.write(accountInfo.get(i));
					out.newLine();
					out.flush();
				}
				
			} catch (IOException e) {
				// error happened
				e.printStackTrace();
			}
		}

		/**
		 * Sets the specified account name to being frozen
		 * @param accntName
		 * @return 
		 */
		public String setFrozen(String accntName){
			String temp = "";
			for(int i=0; i<accountInfo.size(); i++){
				temp = accountInfo.get(i);
				if(temp.contains(accntName)){
					accountInfo.set(i, accntName+"|true|"+temp.substring(temp.lastIndexOf("|")+1));
					save();
					return "Account Frozen!";
				}
			}
			return "Unsuccessful";
		}
		
		/**
		 * Deletes the specified account
		 */
		public String deleteAccount(String accntName){
			String temp = "";
			for(int i=0; i<accountInfo.size(); i++){
				temp = accountInfo.get(i);
				if(temp.contains(accntName) && !temp.contains("true")){
					accountInfo.remove(i);
					save();
					return "Account Deleted.";
				}
			}
			return "Delete Unsuccessful.";
		}
		
		
	}

}
